package com.okex.demo.model;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

/**
 * 持仓信息实体类
 * 表示OKX交易所中的一个持仓信息，包含持仓方向、数量、价格、盈亏等数据
 */
@Data
public class PositionInfo {
    private String instType;        // 产品类型（如SWAP永续合约、SPOT现货等）
    private String mgnMode;         // 保证金模式（isolated：逐仓；cross：全仓）
    private String posId;           // 持仓ID
    private String posSide;         // 持仓方向（long：多仓；short：空仓）
    private BigDecimal pos;         // 持仓数量，正数表示多头，负数表示空头
    private String posCcy;          // 仓位资产币种
    private BigDecimal availPos;    // 可平仓数量
    private BigDecimal avgPx;       // 开仓均价
    private BigDecimal upl;         // 未实现收益（Unrealized Profit/Loss）
    private BigDecimal uplRatio;    // 未实现收益率
    private String instId;          // 产品ID，如BTC-USDT
    private BigDecimal lever;       // 杠杆倍数
    private BigDecimal liqPx;       // 预估强平价格
    private BigDecimal markPx;      // 最新标记价格
    private BigDecimal margin;      // 保证金余额
    private BigDecimal imr;      // 保证金余额
    private BigDecimal mgnRatio;    // 维持保证金率
    private BigDecimal notionalUsd; // 以美金价值为单位的持仓数量
    private BigDecimal last;        // 最新成交价
    private Date updateTime;        // 数据更新时间，用于页面显示
    
    /**
     * 构造函数，初始化更新时间为当前时间
     */
    public PositionInfo() {
        this.updateTime = new Date();
    }
    
    /**
     * 从API返回的JSON对象创建持仓信息实例
     * 
     * @param jsonObject API返回的JSON对象
     * @return 持仓信息实例
     */
    public static PositionInfo fromJsonObject(JSONObject jsonObject) {
        if (jsonObject == null) {
            return null;
        }
        
        PositionInfo position = new PositionInfo();
        position.setInstType(jsonObject.getString("instType"));
        position.setMgnMode(jsonObject.getString("mgnMode"));
        position.setPosId(jsonObject.getString("posId"));
        position.setPosSide(jsonObject.getString("posSide"));
        position.setPos(safeParseDecimal(jsonObject.getString("pos")));
        position.setPosCcy(jsonObject.getString("posCcy"));
        position.setAvailPos(safeParseDecimal(jsonObject.getString("availPos")));
        position.setAvgPx(safeParseDecimal(jsonObject.getString("avgPx")));
        position.setUpl(safeParseDecimal(jsonObject.getString("upl")));
        position.setUplRatio(safeParseDecimal(jsonObject.getString("uplRatio")));
        position.setInstId(jsonObject.getString("instId"));
        position.setLever(safeParseDecimal(jsonObject.getString("lever")));
        position.setLiqPx(safeParseDecimal(jsonObject.getString("liqPx")));
        position.setMarkPx(safeParseDecimal(jsonObject.getString("markPx")));
        position.setMargin(safeParseDecimal(jsonObject.getString("margin")));
        position.setImr(safeParseDecimal(jsonObject.getString("imr")));
        position.setMgnRatio(safeParseDecimal(jsonObject.getString("mgnRatio")));
        position.setNotionalUsd(safeParseDecimal(jsonObject.getString("notionalUsd")));
        position.setLast(safeParseDecimal(jsonObject.getString("last")));
        return position;
    }
    
    /**
     * 安全解析字符串为BigDecimal，避免空值和格式错误导致的异常
     * 
     * @param value 要解析的数字字符串
     * @return 解析结果，如果解析失败则返回0
     */
    private static BigDecimal safeParseDecimal(String value) {
        try {
            return value != null ? new BigDecimal(value) : BigDecimal.ZERO;
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }
    
    /**
     * 判断是否为多头持仓
     * 
     * @return 如果是多头持仓返回true，否则返回false
     */
    public boolean isLong() {
        return "long".equalsIgnoreCase(posSide);
    }
    
    /**
     * 判断是否为空头持仓
     * 
     * @return 如果是空头持仓返回true，否则返回false
     */
    public boolean isShort() {
        return "short".equalsIgnoreCase(posSide);
    }
    
    /**
     * 判断是否为全仓模式
     * 
     * @return 如果是全仓模式返回true，否则返回false
     */
    public boolean isCross() {
        return "cross".equalsIgnoreCase(mgnMode);
    }
    
    /**
     * 判断是否为逐仓模式
     * 
     * @return 如果是逐仓模式返回true，否则返回false
     */
    public boolean isIsolated() {
        return "isolated".equalsIgnoreCase(mgnMode);
    }
    
    /**
     * 获取格式化的未实现盈亏，保留2位小数
     * 
     * @return 格式化后的未实现盈亏
     */
    public BigDecimal getFormattedUpl() {
        return upl != null ? upl.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO;
    }
    
    /**
     * 获取格式化的未实现盈亏率，以百分比表示，保留2位小数
     * 
     * @return 格式化后的未实现盈亏率字符串，如"5.25%"
     */
    public String getFormattedUplRatio() {
        if (uplRatio == null) {
            return "0.00%";
        }
        
        // 将比率乘以100转为百分比，并保留2位小数
        BigDecimal percentage = uplRatio.multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
        return percentage.toPlainString() + "%";
    }
    
    /**
     * 获取格式化的预估强平价格，保留4位小数
     * 
     * @return 格式化后的预估强平价格
     */
    public BigDecimal getFormattedLiqPx() {
        return liqPx != null ? liqPx.setScale(4, RoundingMode.HALF_UP) : BigDecimal.ZERO;
    }
    
    /**
     * 获取持仓方向中文名称
     * 
     * @return 多仓或空仓
     */
    public String getPosSideDisplay() {
        if ("long".equalsIgnoreCase(posSide)) {
            return "多仓";
        } else if ("short".equalsIgnoreCase(posSide)) {
            return "空仓";
        } else {
            return posSide;
        }
    }
    
    /**
     * 获取保证金模式中文名称
     * 
     * @return 全仓或逐仓
     */
    public String getMgnModeDisplay() {
        if ("cross".equalsIgnoreCase(mgnMode)) {
            return "全仓";
        } else if ("isolated".equalsIgnoreCase(mgnMode)) {
            return "逐仓";
        } else {
            return mgnMode;
        }
    }
} 